#include <basic/errcode.h>
#include <basic/datetime.h>
#include <basic/dbc.h>
#include <basic/sqlic.h>

#include <sqlite3.h>

#define _EXPAND_ROWS                20

struct _sqlic
{/*{{{*/
    sqlite3 *db;
};/*}}}*/

int sqlic_init()
{/*{{{*/
    return(0);
}/*}}}*/

int sqlic_clean()
{/*{{{*/
    return(0);
}/*}}}*/

int sqlic_connect(char *dbname, SQLIC *pdb)
{/*{{{*/
    struct _sqlic *db;
    int res;

    if(!pdb)
        return(RET_ERR_PARA);
    *pdb=(SQLIC)NULL;
    if(!dbname || (res=strlen(dbname)) <= 0 || res > LONG_FILE_NM_SIZE)
        return(RET_ERR_PARA);

    ALLOC_RETERR(db, struct _sqlic, RET_ERR_ALLOC);
    if((res=sqlite3_open(dbname, &db->db)) != SQLITE_OK)
        return(res);

    *pdb=db;
    return(SQLI_OK);
}/*}}}*/

int sqlic_disconnect(SQLIC db)
{/*{{{*/
    if(db)
    {
        sqlite3_close(db->db);
        return(SQLI_OK);
    }
    else
        return(RET_ERR_PARA);
}/*}}}*/

int sqlic_begin(SQLIC db)
{/*{{{**/
    if(!db)
        return(RET_ERR_PARA);
    return(sqlite3_exec(db->db, "begin transaction",
                    NULL, NULL, NULL));
}/*}}}*/

int sqlic_commit(SQLIC db)
{/*{{{*/
    if(!db)
        return(RET_ERR_PARA);
    return(sqlite3_exec(db->db, "commit transaction",
                    NULL, NULL, NULL));
}/*}}}*/

int sqlic_rollback(SQLIC db)
{/*{{{**/
    if(!db)
        return(RET_ERR_PARA);
    return(sqlite3_exec(db->db, "rollback transaction",
                    NULL, NULL, NULL));
}/*}}}*/

int sqlic_exec(SQLIC db, char *sql)
{/*{{{*/
    if(!db || !sql)
        return(RET_ERR_PARA);
    return(sqlite3_exec(db->db, sql, NULL, NULL, NULL));
}/*}}}*/

int sqlic_query(SQLIC db, char *sql,
        int request_row_num,
        DBC_RSET *rset)
{/*{{{*/
    sqlite3_stmt *stmt;
    const char *next;
    int col_idx, row_idx;
    int res;

    // 初始化返回结果集
    rset->rows=NULL;
    rset->col_num=0;
    rset->row_num=0;
    rset->row_alloc_num=0;
    rset->query_flag=-1;

    res=sqlite3_prepare(db->db, sql, -1, &stmt, &next);
    if(res != SQLITE_OK)
        return(res);
    rset->col_num=sqlite3_column_count(stmt);

    // 查询结果集分配空间
    if(request_row_num > 0)
    {
        ALLOC_ARRAY_DOERR(rset->rows, char **, request_row_num,
                rset->row_alloc_num,
                sqlite3_finalize(stmt); return(RET_ERR_ALLOC));
        for(row_idx=0; row_idx<request_row_num; row_idx++)
            rset->rows[row_idx]=NULL;
    }

    for (;;)
    {
        res=sqlite3_step(stmt);
        if(res != SQLITE_ROW)
        {
            if(res != SQLITE_DONE)
            {
                sqlite3_finalize(stmt);
                dbc_query_free(rset);
                return(res);
            }
            break;
        }
        rset->row_num++;
        if(request_row_num > 0 &&
           rset->row_num == request_row_num+1)
            break;
        if(rset->row_num > rset->row_alloc_num)
        {
            EXPAND_ARRAY_DOERR(rset->rows, char **, _EXPAND_ROWS,
                    rset->row_alloc_num,
                    sqlite3_finalize(stmt); return(RET_ERR_ALLOC));
            for(row_idx=rset->row_num-1;
                    row_idx<_EXPAND_ROWS; row_idx++)
                rset->rows[row_idx]=NULL;
        }

        // 行
        row_idx=rset->row_num-1;
        ALLOC_MULTI_DOERR(rset->rows[row_idx], char *,
                rset->col_num,
                sqlite3_finalize(stmt); return(RET_ERR_ALLOC));
        for(col_idx=0; col_idx<rset->col_num; col_idx++)
        {
            // 列
            switch(sqlite3_column_type(stmt, col_idx))
            {
                case SQLITE_INTEGER:
                case SQLITE_FLOAT:
                case SQLITE_TEXT:
                case SQLITE_BLOB:
                    rset->rows[row_idx][col_idx]=strdup((char *)
                            sqlite3_column_text(stmt, col_idx));
                    break;
                case SQLITE_NULL:
                    rset->rows[row_idx][col_idx]=strdup(SPACES);
                    break;
                default:
                    break;
            }
            if(rset->rows[row_idx][col_idx] == NULL)
            {
                sqlite3_finalize(stmt);
                return(RET_ERR_ALLOC);
            }
        }
    }
    sqlite3_finalize(stmt);

    /*----- 无记录 -----*/
    if(rset->row_num == 0)
    {
    	dbc_query_free(rset);
		return(SQLI_NO_DATA_FOUND);
    }
    /*----- 查询位置 -----*/
    if(request_row_num > 0 &&
        rset->row_num == request_row_num+1)
    {
        rset->query_flag=QUERY_HALFWAY;
        rset->row_num=request_row_num;
    }
    else
        rset->query_flag=QUERY_BOTTOM;

    return(SQLITE_OK);
}/*}}}*/
